home *** CD-ROM | disk | FTP | other *** search
/ Delphi Magazine Collection 2001 / Delphi Magazine Collection 20001 (2001).iso / Bonus / DBaldwin / litebrows.exe / URLSubs.pas < prev   
Encoding:
Pascal/Delphi Source File  |  2001-06-25  |  8.6 KB  |  346 lines

  1. {Version 8.1}
  2. unit URLSubs;
  3.  
  4. interface
  5.  
  6. uses
  7.   WinTypes, WinProcs, Messages, SysUtils, Liteun2;   
  8.  
  9. function GetBase(const URL: string): string;
  10. {Given an URL, get the base directory}
  11.  
  12. function Combine(Base, APath: string): string;
  13. {combine a base and a path taking into account that overlap might exist}
  14. {needs work for cases where directories might overlap}
  15.  
  16. function Normalize(const URL: string): string;
  17. {lowercase, trim, and make sure a '/' terminates a hostname, adds http://}
  18.  
  19. function IsFullURL(Const URL: string): boolean;
  20. {set if contains http://}
  21.  
  22. function GetProtocol(const URL: string): string;
  23. {return the http, mailto, etc in lower case}
  24.  
  25. function GetURLExtension(const URL: string): string;
  26. {returns extension without the '.', mixed case}
  27.  
  28. function GetURLFilenameAndExt(const URL: string): string;
  29. {returns mixed case after last /}
  30.  
  31. function DosToHTML(FName: string): string;
  32. {convert an Dos style filename to one for HTML.  Does not add the file:///}
  33.  
  34. procedure ParseURL(const url : String; var Proto, User, Pass, Host, Port, Path : String);
  35. {Franτois PIETTE's URL parsing procedure}
  36.  
  37. implementation
  38.  
  39. {----------------GetBase}
  40. function GetBase(const URL: string): string;
  41. {Given an URL, get the base directory}
  42. var
  43.   I, J, LastSlash: integer;
  44.   S: string;
  45. begin
  46. S := Trim(URL);
  47. J := Pos('?', S);    
  48. if J > 0 then
  49.   S := Copy(S, 1, J-1);  {remove Query}
  50. J := Pos('//', S);
  51. LastSlash := 0;
  52. for I := J+2 to Length(S) do
  53.   if S[I] = '/' then LastSlash := I;
  54. if LastSlash = 0 then
  55.   Result := S+'/'
  56. else Result := Copy(S, 1, LastSlash);
  57. end;
  58.  
  59. {----------------Combine}
  60. function Combine(Base, APath: string): string;
  61. {combine a base and a path taking into account that overlap might exist}
  62. {needs work for cases where directories might overlap}
  63. var
  64.   I, J, K: integer;
  65.  
  66. begin
  67. J := Pos('://', Base);
  68. if J > 0 then
  69.   J := Pos('/', Copy(Base, J+3, Length(Base)-(J+2)))+J+2  {third slash}
  70. else
  71.   J := Pos('/', Base);
  72. if J = 0 then
  73.   begin
  74.   Base := Base+'/';   {needs a slash}
  75.   J := Length(Base);
  76.   end
  77. else if Base[Length(Base)] <> '/' then
  78.   Base := Base + '/';
  79.  
  80. APath := Trim(APath);
  81.  
  82. if (APath <> '') and (APath[1] = '/') then
  83.   begin    {remove path from base and use host only}
  84.   if Pos('//', APath) = 1 then      {UNC filename}  
  85.     Result := Copy(Base, 1, J) + APath
  86.   else
  87.     Result := Copy(Base, 1, J) + Copy(APath, 2, Length(APath)-1);
  88.   end
  89. else Result := Base+APath;
  90.  
  91. {remove any '..\'s to simply and standardize for cacheing}
  92. I := Pos('/../', Result);
  93. while I > 0 do
  94.   begin
  95.   if I > J then
  96.     begin
  97.     K := I;
  98.     while (I > 1) and (Result[I-1] <> '/') do
  99.       Dec(I);
  100.     if I <= 1 then Break;
  101.     Delete(Result, I, K-I+4);  {remove canceled directory and '/../'}
  102.     end
  103.   else
  104.     Delete(Result, I+1, 3);    {remove '../' after host name}
  105.   I := Pos('/../', Result);
  106.   end;
  107. {remove any './'s}
  108. I := Pos('/./', Result);
  109. while I > 0 do
  110.   begin
  111.   Delete(Result, I+1, 2);
  112.   I := Pos('/./', Result);
  113.   end;
  114. end;
  115.  
  116. function Normalize(const URL: string): string;
  117. {trim, and make sure a '/' terminates a hostname and http:// is present.
  118.  In other words, if there is only 2 /'s, put one on the end}
  119. var
  120.   I, J, LastSlash: integer;
  121. begin
  122. Result := Trim(URL);
  123. if Pos('://', Result) = 0 then
  124.   Result := 'http://'+Result;       {add http protocol as a default}
  125. J := Pos('/./', Result);
  126. while J > 0 do
  127.   begin
  128.   Delete(Result, J+1, 2);  {remove './'s}
  129.   J := Pos('/./', Result);
  130.   end;
  131. J := Pos('//', Result);
  132. LastSlash := 0;
  133. for I := J+2 to Length(Result) do
  134.   if Result[I] = '/' then LastSlash := I;
  135. if LastSlash = 0 then
  136.   Result := Result+'/'
  137. end;
  138.  
  139. function IsFullURL(Const URL: string): boolean;
  140. var
  141.   N:  integer;
  142. begin
  143. N := Pos('://', URL);
  144. Result := ((N > 0) and (N < Pos('/', URL)) or (Pos('mailto:', Lowercase(URL)) <> 0));
  145. end;
  146.  
  147. function GetProtocol(const URL: string): string;
  148. var
  149.   User, Pass, Port, Host, Path: String;
  150.   S: string;
  151.   I: integer;
  152. begin
  153. I := Pos('?', URL);
  154. if I > 0 then S := Copy(URL, 1, I-1)
  155.   else S := URL;
  156. ParseURL(S, Result, user, pass, Host, port, Path);
  157. Result := Lowercase(Result);
  158. end;
  159.  
  160. function GetURLExtension(const URL: string): string;
  161. var
  162.   I, N: integer;
  163. begin
  164. Result := '';
  165. I := Pos('?', URL);
  166. if I > 0 then N := I-1
  167.   else N := Length(URL);
  168. for I := N downto IntMax(1, N-5) do
  169.   if URL[I] = '.' then
  170.     begin
  171.     Result := Copy(URL, I+1, N-I);   
  172.     Break;
  173.     end;
  174. end;
  175.  
  176. function GetURLFilenameAndExt(const URL: string): string;
  177. var
  178.   I: integer;
  179. begin
  180. Result := URL;
  181. for I := Length(URL) downto 1 do
  182.   if URL[I] = '/' then
  183.     begin
  184.     Result := Copy(URL, I+1, 255);
  185.     Break;
  186.     end;
  187. end;
  188.  
  189. { Find the count'th occurence of the s string in the t string.              }
  190. { If count < 0 then look from the back                                      }
  191. {Thanx to Franτois PIETTE}
  192. function Posn(const s , t : String; Count : Integer) : Integer;
  193. var
  194.     i, h, Last : Integer;
  195.     u          : String;
  196. begin
  197.     u := t;
  198.     if Count > 0 then begin
  199.         Result := Length(t);
  200.         for i := 1 to Count do begin
  201.             h := Pos(s, u);
  202.             if h > 0 then
  203.                 u := Copy(u, h + 1, Length(u))
  204.             else begin
  205.                 u := '';
  206.                 Inc(Result);
  207.             end;
  208.         end;
  209.         Result := Result - Length(u);
  210.     end
  211.     else if Count < 0 then begin
  212.         Last := 0;
  213.         for i := Length(t) downto 1 do begin
  214.             u := Copy(t, i, Length(t));
  215.             h := Pos(s, u);
  216.             if (h <> 0) and ((h + i) <> Last) then begin
  217.                 Last := h + i - 1;
  218.                 Inc(count);
  219.                 if Count = 0 then
  220.                     break;
  221.             end;
  222.         end;
  223.         if Count = 0 then
  224.             Result := Last
  225.         else
  226.             Result := 0;
  227.     end
  228.     else
  229.         Result := 0;
  230. end;
  231.  
  232. { Syntax of an URL: protocol://[user[:password]@]server[:port]/path         }
  233. {Thanx to Franτois PIETTE}
  234. procedure ParseURL(
  235.     const url : String;
  236.     var Proto, User, Pass, Host, Port, Path : String);
  237. var
  238.     p, q : Integer;
  239.     s    : String;
  240. begin
  241.     proto := '';
  242.     User  := '';
  243.     Pass  := '';
  244.     Host  := '';
  245.     Port  := '';
  246.     Path  := '';
  247.  
  248.     if Length(url) < 1 then
  249.         Exit;
  250.  
  251.     p := pos('://',url);
  252.     if p = 0 then begin
  253.         if (url[1] = '/') then begin
  254.             { Relative path without protocol specified }
  255.             proto := 'http';
  256.             p     := 1;
  257.             if (Length(url) > 1) and (url[2] <> '/') then begin
  258.                 { Relative path }
  259.                 Path := Copy(url, 1, Length(url));
  260.                 Exit;
  261.             end;
  262.         end
  263.         else if lowercase(Copy(url, 1, 5)) = 'http:' then begin
  264.             proto := 'http';
  265.             p     := 6;
  266.             if (Length(url) > 6) and (url[7] <> '/') then begin
  267.                 { Relative path }
  268.                 Path := Copy(url, 6, Length(url));
  269.                 Exit;
  270.             end;
  271.         end
  272.         else if lowercase(Copy(url, 1, 7)) = 'mailto:' then begin
  273.             proto := 'mailto';
  274.             p := pos(':', url);
  275.         end;
  276.     end
  277.     else begin
  278.         proto := Copy(url, 1, p - 1);
  279.         inc(p, 2);
  280.     end;
  281.     s := Copy(url, p + 1, Length(url));
  282.  
  283.     p := pos('/', s);
  284.     if p = 0 then
  285.         p := Length(s) + 1;
  286.     Path := Copy(s, p, Length(s));
  287.     s    := Copy(s, 1, p-1);
  288.  
  289.     p := Posn(':', s, -1);
  290.     if p > Length(s) then
  291.         p := 0;
  292.     q := Posn('@', s, -1);
  293.     if q > Length(s) then
  294.         q := 0;
  295.     if (p = 0) and (q = 0) then begin   { no user, password or port }
  296.         Host := s;
  297.         Exit;
  298.     end
  299.     else if q < p then begin  { a port given }
  300.         Port := Copy(s, p + 1, Length(s));
  301.         Host := Copy(s, q + 1, p - q - 1);
  302.         if q = 0 then
  303.             Exit; { no user, password }
  304.         s := Copy(s, 1, q - 1);
  305.     end
  306.     else begin
  307.         Host := Copy(s, q + 1, Length(s));
  308.         s := Copy(s, 1, q - 1);
  309.     end;
  310.     p := pos(':', s);
  311.     if p = 0 then
  312.         User := s
  313.     else begin
  314.         User := Copy(s, 1, p - 1);
  315.         Pass := Copy(s, p + 1, Length(s));
  316.     end;
  317. end;
  318.  
  319. function DosToHTML(FName: string): string;
  320. {convert an Dos style filename to one for HTML.  Does not add the file:///}
  321. var
  322.   Colon: integer;
  323.  
  324.   procedure Replace(Old, New: char);
  325.   var
  326.     I: integer;
  327.   begin
  328.   I := Pos(Old, FName);
  329.   while I > 0 do
  330.     begin
  331.     FName[I] := New;
  332.     I := Pos(Old, FName);
  333.     end;
  334.   end;
  335.  
  336. begin
  337. Colon := Pos('://', FName);
  338. Replace(':', '|');
  339. Replace('\', '/');
  340. if Colon > 0 then
  341.   FName[Colon] := ':';   {return it to a colon} 
  342. Result := FName;
  343. end;
  344.  
  345. end.
  346.